﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Framework
{
    /// <summary>
    /// Mini ASP.NET Core请求处理构造器
    /// </summary>
    public class ApplicationBuilder : IApplicationBuilder
    {
        private readonly List<Func<RequestDelegate, RequestDelegate>> _middlewares = new List<Func<RequestDelegate, RequestDelegate>>();

        /// <summary>
        /// 构建请求处理管道
        /// </summary>
        /// <returns>RequestDelegate</returns>
        public RequestDelegate Build()
        {
            // 倒置注册中间件集合的顺序
            _middlewares.Reverse();
            RequestDelegate handler = new RequestDelegate(HttpHandler);
            return handler;
        }

        private Task HttpHandler(HttpContext context)
        {
            // 注册默认中间件 => 返回404响应
            RequestDelegate notFound = new RequestDelegate(Create404);
            // 构建中间件处理管道
            // 将所有的 middleware 构成的一个单一的 RequestDelegate
            RequestDelegate next = null;
            Func<RequestDelegate, RequestDelegate> middleware = null;
            for (int i = 0; i < _middlewares.Count; i++)
            {
                middleware = _middlewares[i];
                if (i == 0)
                {
                    next = middleware(notFound);
                }
                else
                {
                    next = middleware(next);
                }
            }
            if (next != null)
            {
                return next(context);
            }
            else
            {
                return notFound(context);
            }
        }

        private Task Create404(HttpContext context)
        {
            context.Response.StatusCode = 404;
            return Task.CompletedTask;
        }


        /// <summary>
        /// 注册中间件
        /// </summary>
        /// <param name="middleware">中间件</param>
        /// <returns>ApplicationBuilder</returns>
        public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
        {
            _middlewares.Add(middleware);
            return this;
        }
    }
}
